package org.agile4j.plugin.gun.xml;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.agile4j.plugin.gun.helper.GunHelper;
import org.agile4j.plugin.gun.utils.ParserUtil;
import org.agile4j.plugin.gun.utils.ReplaceContainerUtil;
import org.agile4j.plugin.gun.xml.flowtrans.Block;
import org.agile4j.plugin.gun.xml.flowtrans.Case;
import org.agile4j.plugin.gun.xml.flowtrans.Field;
import org.agile4j.plugin.gun.xml.flowtrans.Fields;
import org.agile4j.plugin.gun.xml.flowtrans.Flow;
import org.agile4j.plugin.gun.xml.flowtrans.Flowtran;
import org.agile4j.plugin.gun.xml.flowtrans.InMappings;
import org.agile4j.plugin.gun.xml.flowtrans.Interface;
import org.agile4j.plugin.gun.xml.flowtrans.Mapping;
import org.agile4j.plugin.gun.xml.flowtrans.Method;
import org.agile4j.plugin.gun.xml.flowtrans.OutMapping;
import org.agile4j.plugin.gun.xml.flowtrans.OutMappings;
import org.agile4j.plugin.gun.xml.flowtrans.OutToPrinterMapping;
import org.agile4j.plugin.gun.xml.flowtrans.PropertyToPrinterMapping;
import org.agile4j.plugin.gun.xml.flowtrans.Report;
import org.agile4j.plugin.gun.xml.flowtrans.Service;
import org.agile4j.plugin.gun.xml.flowtrans.When;
import org.agle4j.framework.utils.CollectionUtil;
import org.agle4j.framework.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@org.agle4j.framework.annotation.Service
public class GunFlowTrans {
	private static final Logger LOGGER = LoggerFactory.getLogger(GunFlowTrans.class);
	
	public boolean createTarFile() {
		return createTarFile(GunHelper.getCreateTarXmlFileUrl()) ;
	}
	
	public boolean createTarFile(String createTarFileUrl) {
		Map<String, Flowtran> flowtranMap = ParserUtil.deplogyTrans(new File(createTarFileUrl));
		LOGGER.debug(JsonUtil.toJson(flowtranMap));
		if (CollectionUtil.isNotEmpty(flowtranMap)) {
			for (Map.Entry<String, Flowtran> flowtranEntry : flowtranMap.entrySet()) {
				Flowtran flowtran = flowtranEntry.getValue();
				if (CollectionUtil.isNotEmpty(flowtran.getDescriptionOrFlowOrInterface())) {
					for (Object obj : flowtran.getDescriptionOrFlowOrInterface()) {
						if (obj instanceof Flow) {
							Flow flow = (Flow) obj ;
							if (CollectionUtil.isNotEmpty(flow.getServiceOrMethodOrReport())) {
								for (Object flowObject : flow.getServiceOrMethodOrReport()) {
									if (flowObject instanceof Service) {
										Service service = (Service) flowObject ;
										replaceService(service);
									}
									if (flowObject instanceof Method) {
										Method method = (Method) flowObject ;
										// nothing to do
									}
									if (flowObject instanceof Report) {
										Report report = (Report) flowObject ;
										replaceReplort(report);
									}
									if (flowObject instanceof Case) {
										Case case1 = (Case) flowObject ;
										replaceCase(case1);
									}
									if (flowObject instanceof Block) {
										Block block = (Block) flowObject ;
										if (CollectionUtil.isNotEmpty(block.getServiceOrMethodOrCase())) {
											for (Object blockObject : block.getServiceOrMethodOrCase()) {
												if (blockObject instanceof Service) {
													Service service = (Service) blockObject ;
													replaceService(service);
												}
												if (blockObject instanceof Method) {
													Method method = (Method) flowObject ;
													// nothing to do
												}
												if (blockObject instanceof Case) {
													Case case2 = (Case) flowObject ;
													replaceCase(case2);
												}
											}
										}
									}
								}
							}
						}
						if (obj instanceof Interface) {
							Interface inter = (Interface) obj ;
							if (inter.getInput() != null) {
								if (CollectionUtil.isNotEmpty(inter.getInput().getFieldOrFields())) {
									for (Object interObj : inter.getInput().getFieldOrFields()) {
										if (interObj instanceof Field) {
											Field field = (Field) interObj ;
											replaceField(field);
										}
										if (interObj instanceof Fields) {
											Fields fields = (Fields) interObj ;
											replaceFields(fields);
										}
									}
								}
							}
							if (inter.getOutput() != null) {
								if (CollectionUtil.isNotEmpty(inter.getOutput().getFieldsOrField())) {
									for (Object outerObj : inter.getOutput().getFieldsOrField()) {
										if (outerObj instanceof Field) {
											Field field = (Field) outerObj ;
											replaceField(field);
										}
										if (outerObj instanceof Fields) {
											Fields fields = (Fields) outerObj ;
											replaceFields(fields);
										}
									}
								}
							}
							if (inter.getPrinter() != null) {
								if (CollectionUtil.isNotEmpty(inter.getPrinter().getFieldOrFields())) {
									for (Object printerObj : inter.getPrinter().getFieldOrFields()) {
										if (printerObj instanceof Field) {
											Field field = (Field) printerObj ;
											replaceField(field);
										}
										if (printerObj instanceof Fields) {
											Fields fields = (Fields) printerObj ;
											replaceFields(fields);
										}
									}
								}
							}
							if (inter.getProperty() != null) {
								if (CollectionUtil.isNotEmpty(inter.getProperty().getFieldOrFields())) {
									for (Object propertyObj : inter.getProperty().getFieldOrFields()) {
										if (propertyObj instanceof Field) {
											Field field = (Field) propertyObj ;
											replaceField(field);
										}
										if (propertyObj instanceof Fields) {
											Fields fields = (Fields) propertyObj ;
											replaceFields(fields);
										}
									}
								}
							}
						}
						if (obj instanceof OutMapping) {
							OutMapping outMapping = (OutMapping) obj ;
							if (CollectionUtil.isNotEmpty(outMapping.getMapping())) {
								replaceMapping(outMapping.getMapping());
							}
						}
						if (obj instanceof OutToPrinterMapping) {
							OutToPrinterMapping outToPrinterMapping = (OutToPrinterMapping) obj ;
							if (CollectionUtil.isNotEmpty(outToPrinterMapping.getMapping())) {
								replaceMapping(outToPrinterMapping.getMapping());
							}
						}
						if (obj instanceof PropertyToPrinterMapping) {
							PropertyToPrinterMapping propertyToPrinterMapping = (PropertyToPrinterMapping) obj ;
							if (CollectionUtil.isNotEmpty(propertyToPrinterMapping.getMapping())) {
								replaceMapping(propertyToPrinterMapping.getMapping());
							}
						}
					}
				}

				File file = new File(flowtranEntry.getKey());
				String tarFilePath = file.getParent() + File.separator + GunHelper.getTarFileFormat() + file.getName(); // 目标文件路径
				ParserUtil.replaceXmlField(tarFilePath, flowtran);
			}
		}
		return true;
	}
	
	private void replaceMapping(List<Mapping> mappingList) {
		for (Mapping mapping : mappingList) {
			if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
				mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
			}
		}
	}
	private void replaceField(Field field) {
		if (ReplaceContainerUtil.containsKey(field.getId())) {
			field.setId(ReplaceContainerUtil.getReplaceValue(field.getId()));
		}
		if (ReplaceContainerUtil.containsKey(field.getRef())) {
			field.setRef(ReplaceContainerUtil.getReplaceValue(field.getId()));
		}
		if (ReplaceContainerUtil.containsKey(field.getType())) {
			field.setType(ReplaceContainerUtil.getReplaceValue(field.getType()));
		}
	}
	
	private void replaceFields(Fields fields) {
		if (ReplaceContainerUtil.containsKey(fields.getId())) {
			fields.setId(ReplaceContainerUtil.getReplaceValue(fields.getId()));
		}
		
		if (CollectionUtil.isNotEmpty(fields.getFieldOrFields())) {
			for (Object fieldsObj : fields.getFieldOrFields()) {
				if (fieldsObj instanceof Field) {
					Field field = (Field) fieldsObj ;
					replaceField(field);
				}
				if (fieldsObj instanceof Fields) {
					Fields fields1 = (Fields) fieldsObj ;
					replaceFields(fields1);
				}
			}
		}
	}
	
	private void replaceService(Service service) {
		if (CollectionUtil.isNotEmpty(service.getInMappingsOrOutMappings())) {
			for (Object mappingObj : service.getInMappingsOrOutMappings()) {
				if (mappingObj instanceof InMappings) {
					InMappings inMappings = (InMappings) mappingObj ;
					if (CollectionUtil.isNotEmpty(inMappings.getMapping())) {
						for (Mapping mapping : inMappings.getMapping()) {
							if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
								mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
							}
						}
					}
				}
				if (mappingObj instanceof OutMappings) {
					OutMappings outMappings = (OutMappings) mappingObj ;
					if (CollectionUtil.isNotEmpty(outMappings.getMapping())) {
						for (Mapping mapping : outMappings.getMapping()) {
							if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
								mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
							}
						}
					}
				}
			}
		}
	}
	
	private void replaceCase(Case case1) {
		if (CollectionUtil.isNotEmpty(case1.getWhen())) {
			for (When when : case1.getWhen()) {
				if (CollectionUtil.isNotEmpty(when.getServiceOrMethod())) {
					for (Object whenObject : when.getServiceOrMethod()) {
						if (whenObject instanceof Service) {
							Service service = (Service) whenObject ;
							if (CollectionUtil.isNotEmpty(service.getInMappingsOrOutMappings())) {
								for (Object mappingObj : service.getInMappingsOrOutMappings()) {
									if (mappingObj instanceof InMappings) {
										InMappings inMappings = (InMappings) mappingObj ;
										if (CollectionUtil.isNotEmpty(inMappings.getMapping())) {
											for (Mapping mapping : inMappings.getMapping()) {
												if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
													mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
												}
											}
										}
									}
									if (mappingObj instanceof OutMappings) {
										OutMappings outMappings = (OutMappings) mappingObj ;
										if (CollectionUtil.isNotEmpty(outMappings.getMapping())) {
											for (Mapping mapping : outMappings.getMapping()) {
												if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
													mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
												}
											}
										}
									}
								}
							}
						}
						
						if (whenObject instanceof Method) {
							Method method = (Method) whenObject ;
							// nothing to do
						}
					}
				}
			}
		}
	}
	
	private void replaceReplort(Report report) {
		if (CollectionUtil.isNotEmpty(report.getInMappingsOrOutMappings())) {
			for (Object mappingObj : report.getInMappingsOrOutMappings()) {
				if (mappingObj instanceof InMappings) {
					InMappings inMappings = (InMappings) mappingObj ;
					if (CollectionUtil.isNotEmpty(inMappings.getMapping())) {
						for (Mapping mapping : inMappings.getMapping()) {
							if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
								mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
							}
						}
					}
				}
				if (mappingObj instanceof OutMappings) {
					OutMappings outMappings = (OutMappings) mappingObj ;
					if (CollectionUtil.isNotEmpty(outMappings.getMapping())) {
						for (Mapping mapping : outMappings.getMapping()) {
							if (ReplaceContainerUtil.containsKey(mapping.getSrc())) {
								mapping.setSrc(ReplaceContainerUtil.getReplaceValue(mapping.getSrc()));
							}
						}
					}
				}
			}
		}
	}
	
}
